package com.bfsd.tieba.agent.tieba_agent.utils;

import com.alibaba.fastjson2.JSONObject;
import com.bfsd.tieba.agent.tieba_agent.config.TiebaConfig;
import com.bfsd.tieba.agent.tieba_agent.enums.Consts;
import jakarta.annotation.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Component
public class RequestUtil {

    @Resource
    private TiebaConfig config;

    @Resource
    RestTemplate restTemplate;

    /**
     * 频繁获取TBS参数会导致失败，tbs可以重复使用，故设置一个map用于管理
     */
    private long lastTbsTime = 0;
    /**
     * 缓存tbs
     */
    private String cachedTbs;
    /**
     * TBS 有效期（秒）
     */
    private static final long TBS_EXPIRE_SECONDS = 10;
    /**
     * 缓存吧名和吧id
     */
    private final Map<String, String> barNameFidMap = new HashMap<>();

    /**
     * 通用请求方式，封装了百度贴吧的通用参数和签名，通过注入类型实现动态响应请求
     *
     * @param params        参数
     * @param url           地址
     * @param responseClazz 返回的类型
     */
    public <T> T executeRequestByUrlAndParam(Map<String, String> params, String url, Class<T> responseClazz) {
        // 基本参数 很多枚举值不知道什么意思，能调通就完事了
        params.put(Consts.CLIENT_TYPE, "2");
        params.put(Consts.CLIENT_VERSION, Consts.CLIENT_VERSION_VALUE);
        params.put(Consts.PHONE_IMEI, "000000000000000");
        params.put(Consts.FROM, Consts.FROM_VALUE);
        params.put(Consts.NET_TYPE, "1");
        params.put(Consts.RN, "50");
        params.put(Consts.WITH_GROUP, Consts.YES);
        params.put(Consts.SORT_TYPE, "5");
        params.put(Consts.FRS_TYPE, "1");
        params.put(Consts.TIMESTAMP, String.valueOf(System.currentTimeMillis()));
        // 生成签名
        String sign = SignUtil.generateSign(params);
        params.put(Consts.SIGN, sign);
        // 转换为form-data
        HttpHeaders headers = new HttpHeaders();
        headers.add(Consts.USER_AGENT, Consts.USER_AGENT_VALUE);
        // 这里不加charset中文会查询报错，排查老半天了
        headers.add(Consts.CONTENT_TYPE, "application/x-www-form-urlencoded; charset=UTF-8");
        headers.add(Consts.COOKIE, config.getCookie());
        StringBuilder body = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (body.length() > 0) body.append("&");
            body.append(entry.getKey()).append("=").append(entry.getValue());
        }
        HttpEntity<String> entity = new HttpEntity<>(body.toString(), headers);
        ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);
        return JSONObject.parseObject(response.getBody(), responseClazz);
    }


    public String getTBS() {
        long currentTime = System.currentTimeMillis();
        // 检查缓存是否有效
        if (cachedTbs != null && !cachedTbs.isEmpty()
                && (currentTime - lastTbsTime < TimeUnit.SECONDS.toMillis(TBS_EXPIRE_SECONDS))) {
            return cachedTbs; // 返回缓存
        }
        // 缓存无效，重新请求
        return fetchAndUpdateTBS();
    }

    public String fetchAndUpdateTBS() {
        HttpHeaders headers = new HttpHeaders();
        headers.add(Consts.USER_AGENT, Consts.USER_AGENT_CHROME);
        headers.add(Consts.COOKIE, config.getCookie());
        HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
        ResponseEntity<String> response = restTemplate.exchange(
                config.getUrls().getTbsTokenUrl(),
                HttpMethod.GET,
                requestEntity,
                String.class
        );
        JSONObject tbsJson = JSONObject.parseObject(response.getBody());
        String newTbs = null;
        if (tbsJson != null) {
            newTbs = tbsJson.getString(Consts.TBS_KEY);
        }
        // 更新缓存和时间戳
        this.cachedTbs = newTbs;
        this.lastTbsTime = System.currentTimeMillis();
        return newTbs;
    }

    public String getFid(String barName) {
        if (barNameFidMap.containsKey(barName)) {
            return barNameFidMap.get(barName);
        }
        HttpHeaders headers = new HttpHeaders();
        headers.add(Consts.USER_AGENT, Consts.USER_AGENT_CHROME);
        headers.add(Consts.COOKIE, config.getCookie());
        HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
        ResponseEntity<String> response = restTemplate.exchange(
                config.getUrls().getFidUrl() + barName,
                HttpMethod.GET,
                requestEntity,
                String.class
        );
        JSONObject fidJson = JSONObject.parseObject(response.getBody());
        String fid = null;
        if (fidJson != null) {
            fid = fidJson.getJSONObject("data").getString("fid");
        }
        barNameFidMap.put(barName, fid);
        return fid;
    }


    /**
     * 从 Cookie 字符串中提取指定字段的值
     *
     * @param key 要提取的字段名（如 "BDUSS"）
     * @return 字段值，未找到时返回 null
     */
    public String extractCookieValue(String key) {
        String cookieStr = config.getCookie();
        if (cookieStr == null || key == null) {
            return null;
        }
        // 正则匹配：key=value（前后可能有空格，值可以包含除分号外的任意字符）
        Pattern pattern = Pattern.compile(key + "=([^;,\\s]+)");
        Matcher matcher = pattern.matcher(cookieStr);
        if (matcher.find()) {
            return matcher.group(1);
        }
        return null;
    }

}
